package org.funny.machine32.hardware.processors.cpu;

import org.funny.machine32.hardware.common.HardwareComponentEnum;
import org.funny.machine32.hardware.common.IHardwareComponent;

import java.util.List;

public class ALU implements IHardwareComponent {

    public int add(int a, int b) {
        return a + b;
    }

    public int sub(int a, int b) {
        return a - b;
    }

    public int mul(int a, int b) {
        return a * b;
    }

    public int div(int a, int b) {
        return a / b;
    }

    public int and(int a, int b) {
        return a & b;
    }

    public int or(int a, int b) {
        return a | b;
    }

    public int nor(int a, int b) {
        return ~(a | b);
    }

    public int xor(int a, int b) {
        return a ^ b;
    }

    public int shiftl(int a, int b) {
        return a << b;
    }

    public int shiftr(int a, int b) {
        return a >> b;
    }

    public int shiftru(int a, int b) {
        return a >>> b;
    }

    @Override
    public String getComponentName() {
        return HardwareComponentEnum.ALU.getName();
    }

    @Override
    public List<IHardwareComponent> getSubComponents() {
        return null;
    }

    @Override
    public void reset() {

    }

    /*

    private Bus bus;
    private Register a, c;
    private int wordSize;
    private int maxImmediate;
    //Flags flags;
    private FlagRegister flags;
    public boolean flagO;
    public boolean flagZ;
    public boolean flagS;

    public ALU(Register a, Register c, Bus bus, FlagRegister flags, int maxImmediate) {
        this.a = a;
        this.c = c;
        this.bus = bus;
        this.flags = flags;
        //this.wordSize = a.wordSize();
        this.maxImmediate = maxImmediate;
    }

    @Override
    public void reset() {
        bus.reset();
        a.reset();
        c.reset();
        flags.reset();
    }

    public byte[] add(byte[] a, byte[] b) {
        int result = BinUtils.byteArrayToInt(a) + BinUtils.byteArrayToInt(b);
        setFlags(result, false);
        return BinUtils.intToByteArray(result);
    }

    public byte[] sub(byte[] a, byte[] b) {
        int result = BinUtils.byteArrayToInt(a) - BinUtils.byteArrayToInt(b);
        setFlags(result, false);
        return BinUtils.intToByteArray(result);
    }

    public byte[] and(byte[] a, byte[] b) {
        int result = BinUtils.byteArrayToInt(a) & BinUtils.byteArrayToInt(b);
        setFlags(result, false);
        return BinUtils.intToByteArray(result);
    }

    public byte[] xor(byte[] a, byte[] b) {
        int result = BinUtils.byteArrayToInt(a) ^ BinUtils.byteArrayToInt(b);
        setFlags(result, false);
        return BinUtils.intToByteArray(result);
    }

    //======================

    public void add(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData + busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void add(int val, boolean fetch) {
        int busData = bus.readInt();
        int result = val + busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void sub(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData - busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void sub(int val, boolean fetch) {
        int busData = bus.readInt();
        int result = busData - val;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void multiply(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData * busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void and(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData & busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void or(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData | busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void xor(boolean fetch) {
        int aData = a.readInt();
        int busData = bus.readInt();
        int result = aData ^ busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    public void not(boolean fetch) {
        int busData = bus.readInt();
        int result = ~busData;
        setFlags(result, fetch);
        c.writeInt(result);
    }

    private void setFlags(int result, boolean fetch) {
        // if this instructionset a fetch operation then don't set flags
        //(to preserve flags from last operation)
        if (fetch) return;
        flagO = (result > maxImmediate || result < (-maxImmediate));
        flagZ = (result == 0);
        flagS = (result < 0);
    }

    */
}
